import queue
import socket
import threading


# 客户端线程处理类
class ClientThreadHandle:
    def __init__(self, conn_object: socket, separator="7E"):
        #  实例化先进先出队列类
        self.data_queue = queue.Queue(maxsize=10)
        self.conn_object = conn_object
        self.threading_dict = {}
        self.separator = separator  # 分隔符

        self.client_state = True  # 客户端的状态

    def __del__(self):
        # ClientThreadHandle对象销毁时
        print("实例结束了", self.conn_object)

    def run(self):
        #  开启客户端线程处理
        self.threading_dict["qut_data"] = threading.Thread(target=self.put_data, args=())
        self.threading_dict["data_processing"] = threading.Thread(target=self.data_processing, args=())

        self.threading_dict["qut_data"].start()
        self.threading_dict["data_processing"].start()

    def put_data(self):
        # 将处理分包粘包后的数据写入队列
        buffer = ""

        while self.client_state:  # 当判断到客户端断开则退出线程
            try:
                data = self.recv_network_data()
                if data != "":  # 若socket数据为空，则不写入队列
                    data = buffer + data  # 拼接未匹配的字符串继续进行分包粘包处理
                    network_packet_list, buffer = self.search_packet_head_tail(data, self.separator)

                    if len(network_packet_list) > 0:
                        for network_packet in network_packet_list:
                            self.data_queue.put(network_packet)

            except ConnectionResetError as error_msg:  # 客户端断开连接后退出线程
                print(error_msg)

    def data_processing(self):
        # 出队列，阻塞型
        while self.client_state:  # 若客户端断开连接则退出此消费者线程

            try:
                data = self.data_queue.get(timeout=1)
                print(data)
            except Exception as error:
                print(error)
                continue

    def recv_network_data(self) -> str:
        # 封装读取socket client数据,若client断开则改变client状态
        try:
            data = self.conn_object.recv(1024).decode("gbk")
            data = data.replace('\n', "")
            data = data.replace(' ', "")
            if data == "":
                self.client_state = False
            return data
        except ConnectionResetError as error:
            print("当前客户端主动断开了连接,退出所有线程")
            self.client_state = False

    @staticmethod
    def search_packet_head_tail(buf: str, tag: str):
        # 处理分包，粘包现象

        tag_head_index = -1
        tag_end_index = -1
        buf_len = len(buf)
        re_list, re_str = [], ""  # 初始化返回值的类型
        find_start = 0

        while True:
            index = buf.find(tag, find_start, buf_len)
            if index >= 0:
                if tag_head_index < 0:  # 当未找到头部分隔符时，给head索引变量赋值
                    tag_head_index = index

                else:
                    tag_end_index = index  # 当未找到尾部分隔符时，给end索引变量赋值
                    re_list.append(buf[tag_head_index:tag_end_index + 2])  # 将已找到的一组数据包加入返回值list内

                    # 初始化头尾索引
                    tag_head_index = -1
                    tag_end_index = -1
                find_start = index + 2  # 将查找开始索引推进到7E后2位

            else:
                if find_start == 0 and tag_head_index == -1:  # 代表这次数据包没有包含分隔符，所以返回所有字符串
                    re_str = buf
                elif find_start == buf_len and tag_head_index == -1:  # 没有字符串在分隔符外时
                    re_str = ""
                elif tag_head_index != -1 and tag_end_index == -1:  # 只找到头部但没有尾部分隔符时
                    re_str = buf[find_start - 2:]
                else:
                    re_str = buf[find_start:]  # 找完所有包后，将剩下的的数据包返回

                break

        return re_list, re_str


if __name__ == '__main__':
    pass
